//! # 认证上下文
//!
//! 包含认证所需的所有请求信息，在整个 RustCloud 生态系统中统一使用。

use std::collections::HashMap;
use std::time::SystemTime;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;

#[cfg(feature = "axum-integration")]
use axum::http::HeaderMap;

#[cfg(not(feature = "axum-integration"))]
type HeaderMap = HashMap<String, String>;

/// 认证上下文
/// 
/// 包含认证所需的所有请求信息，在整个 RustCloud 生态系统中统一使用
#[derive(Debug, Clone)]
pub struct AuthContext {
    /// HTTP 请求头
    pub headers: HeaderMap,
    /// HTTP 方法
    pub method: String,
    /// 请求URI
    pub uri: String,
    /// 客户端IP地址
    pub remote_addr: Option<String>,
    /// 查询参数
    pub query_params: HashMap<String, String>,
    /// 请求体（可选）
    pub body: Option<Vec<u8>>,
    /// 请求时间戳
    pub timestamp: SystemTime,
    /// 扩展属性
    pub extensions: HashMap<String, String>,
}

impl AuthContext {
    /// 创建新的认证上下文
    pub fn new(
        headers: HeaderMap,
        method: String,
        uri: String,
        remote_addr: Option<String>,
    ) -> Self {
        Self {
            headers,
            method,
            uri,
            remote_addr,
            query_params: HashMap::new(),
            body: None,
            timestamp: SystemTime::now(),
            extensions: HashMap::new(),
        }
    }

    /// 添加查询参数
    pub fn with_query_params(mut self, query_params: HashMap<String, String>) -> Self {
        self.query_params = query_params;
        self
    }

    /// 添加请求体
    pub fn with_body(mut self, body: Vec<u8>) -> Self {
        self.body = Some(body);
        self
    }

    /// 添加扩展属性
    pub fn with_extension(mut self, key: String, value: String) -> Self {
        self.extensions.insert(key, value);
        self
    }

    /// 获取Bearer令牌
    pub fn get_bearer_token(&self) -> Option<String> {
        #[cfg(feature = "axum-integration")]
        {
            self.headers
                .get("authorization")
                .and_then(|v| v.to_str().ok())
                .and_then(|auth| {
                    if auth.starts_with("Bearer ") {
                        Some(auth[7..].to_string())
                    } else {
                        None
                    }
                })
        }

        #[cfg(not(feature = "axum-integration"))]
        {
            self.headers
                .get("authorization")
                .and_then(|auth| {
                    if auth.starts_with("Bearer ") {
                        Some(auth[7..].to_string())
                    } else {
                        None
                    }
                })
        }
    }

    /// 获取API Key（从header或query参数）
    pub fn get_api_key(&self) -> Option<&str> {
        // 首先检查query参数
        if let Some(api_key) = self.query_params.get("api_key") {
            return Some(api_key);
        }

        // 然后检查headers
        #[cfg(feature = "axum-integration")]
        {
            self.headers
                .get("x-api-key")
                .and_then(|v| v.to_str().ok())
        }

        #[cfg(not(feature = "axum-integration"))]
        {
            self.headers.get("x-api-key").map(|s| s.as_str())
        }
    }

    /// 获取Basic认证信息
    pub fn get_basic_auth(&self) -> Option<(String, String)> {
        #[cfg(feature = "axum-integration")]
        {
            self.headers
                .get("authorization")
                .and_then(|v| v.to_str().ok())
                .and_then(|auth| {
                    if auth.starts_with("Basic ") {
                        let encoded = &auth[6..];
                        STANDARD.decode(encoded).ok()
                            .and_then(|decoded| String::from_utf8(decoded).ok())
                            .and_then(|decoded| {
                                let parts: Vec<&str> = decoded.splitn(2, ':').collect();
                                if parts.len() == 2 {
                                    Some((parts[0].to_string(), parts[1].to_string()))
                                } else {
                                    None
                                }
                            })
                    } else {
                        None
                    }
                })
        }

        #[cfg(not(feature = "axum-integration"))]
        {
            self.headers
                .get("authorization")
                .and_then(|auth| {
                    if auth.starts_with("Basic ") {
                        let encoded = &auth[6..];
                        STANDARD.decode(encoded).ok()
                            .and_then(|decoded| String::from_utf8(decoded).ok())
                            .and_then(|decoded| {
                                let parts: Vec<&str> = decoded.splitn(2, ':').collect();
                                if parts.len() == 2 {
                                    Some((parts[0].to_string(), parts[1].to_string()))
                                } else {
                                    None
                                }
                            })
                    } else {
                        None
                    }
                })
        }
    }

    /// 获取客户端IP地址
    pub fn get_client_ip(&self) -> Option<&str> {
        self.remote_addr.as_deref()
    }

    /// 获取扩展属性
    pub fn get_extension(&self, key: &str) -> Option<&str> {
        self.extensions.get(key).map(|s| s.as_str())
    }

    /// 检查是否为安全连接
    pub fn is_secure(&self) -> bool {
        self.uri.starts_with("https://") || 
        self.extensions.get("secure").map_or(false, |v| v == "true")
    }
}

impl Default for AuthContext {
    fn default() -> Self {
        Self::new(
            Default::default(),
            "GET".to_string(),
            "/".to_string(),
            None,
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_auth_context_creation() {
        let context = AuthContext::new(
            Default::default(),
            "POST".to_string(),
            "/api/login".to_string(),
            Some("192.168.1.100".to_string()),
        );
        
        assert_eq!(context.method, "POST");
        assert_eq!(context.uri, "/api/login");
        assert_eq!(context.remote_addr, Some("192.168.1.100".to_string()));
    }

    #[test]
    fn test_query_params() {
        let mut query_params = HashMap::new();
        query_params.insert("api_key".to_string(), "test123".to_string());
        
        let context = AuthContext::new(
            Default::default(),
            "GET".to_string(),
            "/api/test".to_string(),
            None,
        ).with_query_params(query_params);
        
        assert_eq!(context.get_api_key(), Some("test123"));
    }

    #[test]
    fn test_extension() {
        let context = AuthContext::new(
            Default::default(),
            "GET".to_string(),
            "/api/test".to_string(),
            None,
        ).with_extension("custom_field".to_string(), "custom_value".to_string());
        
        assert_eq!(context.get_extension("custom_field"), Some("custom_value"));
    }

    #[test]
    fn test_is_secure() {
        let mut context = AuthContext::new(
            Default::default(),
            "GET".to_string(),
            "https://example.com/api".to_string(),
            None,
        );
        
        assert!(context.is_secure());
        
        context.uri = "http://example.com/api".to_string();
        assert!(!context.is_secure());
        
        context = context.with_extension("secure".to_string(), "true".to_string());
        assert!(context.is_secure());
    }
}